"""数据处理模块"""

import csv
import re
import importlib
import inspect
import yaml
from contextlib import ExitStack
from jinja2 import FileSystemLoader, Environment
from config import PATH

"""csv数据路劲"""
csv_path = PATH + "/data/data_csv/"
"""yaml模板路劲"""
data_templates_path = PATH + "/data/data_templates/"
"""yaml测试数据路劲"""
data_test = PATH + "/data/test_data/"


class ReadData:
    @staticmethod
    def writ_yaml_ex(data):
        """
        写入中间值的yaml文件，判断文件中是否存在相同的key值，存在则不写入
        :param data:
        :return:
        """
        if not ReadData.read_yaml_ex(*data):
            with open(PATH + "/extract.yaml", mode="a", encoding="utf-8") as f:
                yaml.dump(data=data, stream=f, allow_unicode=True)

    @staticmethod
    def read_yaml_ex(key):
        """
        按键读取接口的中间值
        :param key:
        :return: 读出成功返回该值，失败返回false
        """
        with open(PATH + "/extract.yaml", encoding="utf-8") as f:
            try:
                res = yaml.safe_load(f)[key]
                return res
            except Exception as e:
                return False

    @staticmethod
    def yaml_clear_ex():
        """清空中间值"""
        with open(PATH + "/extract.yaml", mode='w', encoding="utf-8") as f:
            f.truncate()

    @classmethod
    def read_yaml(cls, file_name, **kwargs):
        """
        读取yaml文件
        :param file_name:文件名字
        :return:
        """
        try:
            with open(data_test + file_name, encoding="utf-8") as f:
                return yaml.safe_load(f)
        except:
            # 批量生成yaml
            data_path = cls.__create_test_data(file_name, **kwargs)
            # 写入动态参数的yaml
            cls._read_yaml_dynamic(data_path)
            with open(data_test + file_name, encoding="utf-8") as f:
                return yaml.safe_load(f)

    @classmethod
    def read_yaml_list(cls, file_name_list, **kwargs):
        """
        读取yaml文件
        :return:
        """
        yaml_list = []
        for file_name in file_name_list:
            try:
                with open(data_test + file_name, encoding="utf-8") as f:
                    for i in yaml.safe_load(f):
                        yaml_list.append(i)
            except FileNotFoundError as e:
                # 批量生成yaml
                data_path = cls.__create_test_data(file_name, **kwargs)
                # 写入动态参数的yaml
                cls._read_yaml_dynamic(data_path)
                with open(data_test + file_name, encoding="utf-8") as f:
                    for i in yaml.safe_load(f):
                        yaml_list.append(i)
        return yaml_list

    @classmethod
    def _dynamic_parameters(cls, file_name, **kwargs):
        """
        动态参数加载
        :param file_name: 文件名字
        :param kwargs: 不知道
        :return: 文件对象
        """
        # 获取数据模块路径
        mode = FileSystemLoader(data_test)
        # 动态函数加载
        return Environment(loader=mode).get_template(file_name).render(**kwargs)

    @staticmethod
    def _dynamic_mode(module_path):
        """
        动态获取函数模板
        :param module_path: 模块路劲
        :return: 不知道
        """
        # 加载模块路径
        module = importlib.import_module(module_path)
        # 动态获得该模块的所有函数
        all_function = inspect.getmembers(module, inspect.isfunction)
        # 已字典形式返回
        return dict(all_function)

    @classmethod
    def _read_yaml_dynamic(cls, file_name, module_path='utility.dynamic_functions'):
        """
        读取含有python函数的yaml文件
        :param file_name: 数据文件名字
        :param module_path: 动态函数存在的模块路径(默认指定文件夹)
        :return: 指定yaml文件数据
        """
        f = cls._dynamic_parameters(file_name, **cls._dynamic_mode(module_path))
        data = yaml.safe_load(f)
        # 重新写入文件
        with open(data_test + file_name, 'w', encoding='utf-8') as f:
            yaml.dump(data=data, stream=f, allow_unicode=True, sort_keys=False)

    @staticmethod
    def __create_test_data(csv_file, data_template=None, test_data=None):
        """
        csv数据根据yaml模板批量生成yaml文件，（$csv{}提取标识

        最好三种数据名字一样

        :param csv_file: csv文件
        :param data_template: yaml文件模板
        :param test_data: 要写入的新yaml文件
        :return: 返回新yaml文件的名字
        """
        if not (data_template and test_data):
            data_template = test_data = csv_file
        new_yaml1 = test_data
        # 后缀名yaml改为csv
        csv_file = csv_file.replace('yaml', 'csv')
        csv_file = csv_path + csv_file
        old_yaml = data_templates_path + data_template
        new_yaml = data_test + test_data
        profileList = []
        with open(csv_file, 'r', encoding='utf-8') as csv_file:
            # 读取csv文件
            reader = csv.DictReader(csv_file)
            for row in reader:
                # 转换为字典类型
                profileList.append(dict(row))
        with ExitStack() as stack:
            # 获取上下文管理器
            yml_file = stack.enter_context(open(old_yaml, 'r+', encoding='utf-8'))
            yml_output = stack.enter_context(open(new_yaml, 'w', encoding='utf-8'))
            # 先读取YAML模板文件，返回值为字符串列表
            yml_file_lines = yml_file.readlines()
            # 遍历每条测试用例（遍历数即用例测试数
            for i in profileList:
                # 获取yaml文件中的每行数据（以字符串形式
                for line in yml_file_lines:
                    # 正则匹配到想要的数据
                    resp = re.search('\$csv{(.+?)}', line)
                    # 判断提取到的是否存在yaml每行数据中
                    if resp:
                        resp = resp.group(1)
                        # 存在拿出来对应的值
                        value = i.get(resp)
                        # 判断是否非空
                        if value:
                            # 替换掉yaml每行对应的值
                            for _ in profileList:
                                line = line.replace('$csv{' + resp + '}', value)
                        else:
                            line = ''
                    # 写入新yaml文件
                    yml_output.write(line)
                # 写入一个用例
                yml_output.write("\n")
            # 返回存在新文件的名字
        return new_yaml1


if __name__ == '__main__':
    print(ReadData.read_yaml('add.yaml'))
